#include <bits/stdc++.h>
using namespace std;
//definition
const int MAXN = 1e5 + 100,MAXM = 1e5 + 100,MAXL = 1e6 + 100,MAXV = 1e3 + 100,INF = 0x3f3f3f3f;
int T,Cars,Sensors,Sensor[MAXM],Road_Len,Limit_Speed;
struct Node{
    int In;
    int V;
    int A;
};
Node Car[MAXN];
bool Check_A,Check_B,Check_C,Vis[MAXL];
int Latest_In,Earliest_Out;

//caculate Vt from a,V0,delta_x
int Cacu(int V,int Ad,int DX){
    return (2 * Ad * DX) + (V * V);
}

//Spacial cacu delta X when A < 0
int Special_Cacu(int V,int Ad){
    //int MAd = 0 - Ad;
    return abs(V * V / Ad);
}

//compare(judge) speed whether be above the limit.Above -> true;Below -> false;
bool Check(int Speed){
    int L = Limit_Speed * Limit_Speed;
    if(Speed > L){
        return true;
    }
    else if(Speed <= L){
        return false;
    }
}

int main(){
    freopen("detect.in","r",stdin);
    freopen("detect.out","w",stdout);
    //
    //

    //input
    scanf("%d",&T);
    //main
    while(T--){
        //init
        memset(Car,0,sizeof(Cars));
        memset(Sensor,0,sizeof(Sensor));
        memset(Vis,false,sizeof(Vis));
        Check_A = true;
        Check_B = true;
        Check_C = true;

        //input
        scanf("%d%d%d%d",&Cars,&Sensors,&Road_Len,&Limit_Speed);
        for(int i = 0;i < Cars;i ++){
            scanf("%d%d%d",&Car[i].In,&Car[i].V,&Car[i].A);
            //Special Data
            Latest_In = max(Latest_In,Car[i].In);
            if(Car[i].A != 0){Check_A = false;}
            if(Car[i].A <= 0){Check_B = false;}
            if(Car[i].A >= 0){Check_C = false;}
        }
        for(int i = 0;i < Sensors;i ++){
            scanf("%d",&Sensor[i]);
        }

        //Special

    //Special 1
        if(Cars <= 10 and Sensors <= 20){
            //Operation 1
            int Cnt1 = 0;
            bool NT = false;
            for(int i = 0;i < Cars;i ++){
                NT = false;
                int Max_Delta_X = -1;
                if(Car[i].A < 0){
                    Max_Delta_X = Special_Cacu(Car[i].V,Car[i].A);
                }
                for(int j = 0;j < Sensors;j ++){
                    if(NT == true){
                        NT = false;
                        break;
                    }
                    if(Sensor[j] < Car[i].In){
                        continue;
                    }
                    if(Car[i].A >= 0 and Check(Cacu(Car[i].V,Car[i].A,Sensor[i] - Car[i].In)) == true){
                        Cnt1 ++;
                        NT = true;
                    }
                    else if(Car[i].A < 0){
                        if(Sensor[j] - Car[i].In > Max_Delta_X){
                            NT = true;
                        }
                        else{
                            if(Check(Cacu(Car[i].V,Car[i].A,Sensor[j] - Car[i].In)) == true){
                                Cnt1 ++;
                                NT = true;
                            }
                        }
                    }
                }
            }

            //Operation 2
            int Cnt2 = 0;
            bool Must_Stay[MAXM];
            memset(Must_Stay,false,sizeof(Must_Stay));
            for(int i = 0;i < Cars;i ++){
                if(Car[i].A >= 0){
                    for(int j = 0;j < Sensors;j ++){
                        if(Sensor[j] >= Car[i].In){
                            Must_Stay[j] = true;
                        }
                    }
                }
                else if(Car[i].A < 0){
                    int Max_Delta_X = Special_Cacu(Car[i].V,Car[i].A);
                    for(int j = 0;j < Sensors;j ++){
                        if(Sensor[j] >= Car[i].In and (Sensor[j] - Car[i].In) <= Max_Delta_X){
                            Must_Stay[j] = true;
                        }
                        else if(Sensor[j] - Car[i].In > Max_Delta_X){
                            break;
                        }
                    }
                }
            }
            for(int i = 0;i < Sensors;i ++){
                if(Must_Stay[i] == true){
                    Cnt2 ++;
                }
            }

            //output
            printf("%d %d\n",Cnt1,Cnt2);
        }


    //Special A
        else if(Check_A == true and Check_B == false and Check_C == false){
            //Operation 1
            int Cnt = 0;
            for(int i = 0;i < Cars;i ++){
                if(Car[i].V > Limit_Speed){
                    Cnt ++;
                }
            }

            //Operation 2
            //Max_Delete = Sensors - 1

            //output
            printf("%d %d\n",Cnt,Sensors - 1);
        }


    //Special B
        else if(Check_A == false and Check_B == true and Check_C == false){
            //Operation 1
            int Cnt1 = 0;
            for(int i = 0;i < Cars;i ++){
                for(int j = 0;j < Sensors;j ++){
                    if(Check(Cacu(Car[i].V,Car[i].A,Sensor[i] - Car[i].In))){
                        Cnt1 ++;
                continue;
                    }
                }
            }

            //Operation
            int Cnt2 = 0;
            bool Must_Stay[MAXM];
            memset(Must_Stay,false,sizeof(Must_Stay));
            for(int i = 0;i < Cars;i ++){
                for(int j = 0;j < Sensors;j ++){
                    if(Sensor[j] >= Car[i].In){
                        Must_Stay[j] = true;
                    }
                }
            }
            for(int i = 0;i < Sensors;i ++){
                if(Must_Stay[i] == true){
                    Cnt2 ++;
                }
            }

            //output
            printf("%d %d\n",Cnt1,Cnt2);
        }

    //Special C
        else if(Check_A == false and Check_B == false and Check_C == true){
            //Operation 1
            int Cnt1 = 0;
            for(int i = 0;i < Cars;i ++){
                for(int j = 0;j < Sensors;j ++){
                    if(Check(Cacu(Car[i].V,Car[i].A,Sensor[i] - Car[i].In))){
                        Cnt1 ++;
                continue;
                    }
                }
            }

            //Operation 2
            int Cnt2 = 0;
            bool Must_Stay[MAXM];
            memset(Must_Stay,false,sizeof(Must_Stay));
            for(int i = 0;i < Cars;i ++){
                int Max_Delta_X = Special_Cacu(Car[i].V,Car[i].A);
                for(int j = 0;j < Sensors;j ++){
                    if(Sensor[j] <= Max_Delta_X){
                        Must_Stay[j] = true;
                    }
                    else if(Sensor[j] > Max_Delta_X){
                        break;
                    }
                }
            }
            for(int i = 0;i < Sensors;i ++){
                if(Must_Stay[i] == true){
                    Cnt2 ++;
                }
            }

            //output
            printf("%d %d\n",Cnt1,Cnt2);
        }

    //Common
        else{
            //Operation 1
            int Cnt1 = 0;
            for(int i = 0;i < Cars;i ++){
                for(int j = 0;j < Sensors;j ++){
                    if(Check(Cacu(Car[i].V,Car[i].A,Sensor[i] - Car[i].In))){
                        Cnt1 ++;
                continue;
                    }
                }
            }

            //Operation 2
            int Cnt2 = 0;
            bool Must_Stay[MAXM];
            memset(Must_Stay,false,sizeof(Must_Stay));
            for(int i = 0;i < Cars;i ++){
                if(Car[i].A >= 0){
                    for(int j = 0;j < Sensors;j ++){
                        if(Sensor[j] >= Car[i].In){
                            Must_Stay[j] = true;
                        }
                    }
                }
                else if(Car[i].A < 0){
                    int Max_Delta_X = Special_Cacu(Car[i].V,Car[i].A);
                    for(int j = 0;j < Sensors;j ++){
                        if(Sensor[j] <= Max_Delta_X){
                            Must_Stay[j] = true;
                        }
                        else if(Sensor[j] > Max_Delta_X){
                            break;
                        }
                    }
                }
            }
            for(int i = 0;i < Sensors;i ++){
                if(Must_Stay[i] == true){
                    Cnt2 ++;
                }
            }

            //output
            printf("%d %d\n",Cnt1,Cnt2);
        }

    }

    //
    //
    fclose(stdin);
    fclose(stdout);
    return 0;
}
